package net.tplusplus.rules.runner;

import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Iterator;

import net.tplusplus.rules.runner.rao.Fact;
import net.tplusplus.rules.runner.rao.Global;

import org.drools.FactHandle;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import org.drools.WorkingMemory;
import org.drools.compiler.PackageBuilder;
import org.drools.spi.ActivationGroup;
import org.drools.spi.AgendaGroup;


public class StatefulRunner
{
	private RuleBase ruleBase;
	private StatefulSession workingMemory;
	
	private List<String> rules;
	private List<Global> globals;
	private List<Fact> facts;
	
	public StatefulRunner()
	{
		rules = new ArrayList<String>();
		globals = new ArrayList<Global>();
		facts = new ArrayList<Fact>();	
	}
	
	public void addRules(String... rules)
	{
		this.rules.addAll(Arrays.asList(rules));
	}
	
	public void addGlobals(Global... globals)
	{
		this.globals.addAll(Arrays.asList(globals));
	}
	
	public void addFacts(Fact... facts)
	{
		this.facts.addAll(Arrays.asList(facts));
	}
	
	public void addFacts(List<? extends Fact> facts)
	{
		this.facts.addAll(facts);
	}	
	
	public List<Fact> getFacts()
	{
		return this.facts;
	}
	
	public void clearFacts()
	{
		this.facts = new ArrayList<Fact>();
	}
	
	public void dispose()
	{
		if(workingMemory!=null)
		{
			workingMemory.dispose();
			workingMemory=null;
		}
	}
	
	public RuleBase createRuleBase()
	throws Exception
	{
		if(rules==null)
		{
			throw new Exception("No rules provided for Engine");
		}
		
		ruleBase = RuleBaseFactory.newRuleBase();
		PackageBuilder builder = new PackageBuilder();		
		
		for(String ruleFile : rules)
		{
			URL resource = this.getClass().getResource(ruleFile);
			
			if(resource==null)
			{
				System.err.println("Could not find resource: "+ruleFile);
				continue;
			}

			File file = new File(this.getClass().getResource(ruleFile).getPath());
			if(!file.exists())
			{
				System.err.println("Could not find rule file: "+file.getPath());
				continue;
			}
			
			builder.addPackageFromDrl(new FileReader(file.getPath()));
		}
		
		org.drools.rule.Package pkg = builder.getPackage();		
		ruleBase.addPackage(pkg);	
		
		return ruleBase;
	}
	
	public void setRuleBase(RuleBase ruleBase)
	{
		this.ruleBase = ruleBase;
	}
	
	public RuleBase getRuleBase()
	{
		return ruleBase;
	}
	
	public WorkingMemory createWorkingMemory()
	throws Exception
	{
		if(ruleBase==null)
		{
			createRuleBase();
		}
		
		workingMemory = null;
		
		workingMemory = ruleBase.newStatefulSession();
		
		return workingMemory;
	}
	
	public void setWorkingMemory(StatefulSession workingMemory)
	{
		this.workingMemory = workingMemory;
	}
	
	public StatefulSession getWorkingMemory()
	{
		return workingMemory;
	}
	
	public void runRules()
	throws Exception
	{		
		if(workingMemory==null)
		{
			throw new Exception("No workingMemory created for Engine");
		}
				
		if(globals!=null)
		{
			for(Global global : globals)
			{
				workingMemory.setGlobal(global.getName(), global.getValue());
			}
		}

		if(facts!=null)
		{
			for(Fact fact : facts)
			{
				workingMemory.insert(fact);
			}
		}

		workingMemory.fireAllRules();
	}
}
